package com.prj.ufdm.webflux.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import org.springframework.context.ApplicationContext;
import com.prj.ufdm.webflux.annotation.ApiClient;
import com.prj.ufdm.webflux.bpo.DeviceHandler;
import com.prj.ufdm.webflux.constants.WebFluxConstants;
import com.prj.ufdm.webflux.enums.ClientType;

/**
 * DESC: 默认DeviceHandler处理代理类
 * 
 * @author Administrator
 */
public class DynamicDeviceDefaultHandlerProxy implements InvocationHandler {

	private String className;
	private ApplicationContext applicationContext;

	private Map<ClientType, Object> clientMap = new HashMap<>(2);

	public DynamicDeviceDefaultHandlerProxy(String className, ApplicationContext applicationContext) {
		this.className = className;
		this.applicationContext = applicationContext;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if (clientMap.size() == 0) {
			initClientMap();
		}
		if(this.className.equals(DeviceHandler.class.getName())) {
			Object obj =  clientMap.get(WebFluxConstants.DEFAULT_CLIENT_TYPE);
			return method.invoke(obj, args);
		}
		else {
			return method.invoke(proxy, args);
		}
	}
		
	private void initClientMap() throws ClassNotFoundException {
		// 获取classStr 接口的所有实现类
		Map<String, ?> classMap = applicationContext.getBeansOfType(Class.forName(className));
		for (Map.Entry<String, ?> entry : classMap.entrySet()) {
			// 根据ApiClientType注解将实现类分为Feign和Url两种类型
			ApiClient apiClient = entry.getValue().getClass().getAnnotation(ApiClient.class);
			if (apiClient == null) {
				continue;
			}
			clientMap.put(apiClient.type(), entry.getValue());
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T newMapperProxy(String className,ApplicationContext applicationContext) throws ClassNotFoundException {
		Class<?> mapperInterface = Class.forName(className);
		ClassLoader classLoader = mapperInterface.getClassLoader();
		Class<?>[] interfaces = new Class[] { mapperInterface };
		DynamicDeviceDefaultHandlerProxy proxy = new DynamicDeviceDefaultHandlerProxy(className,applicationContext);
		return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
	}
}
